package com.ys.service.finance.impl;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ys.dto.AddDto;
import com.ys.dto.EditDto;
import com.ys.entity.finance.TcwWanliPrepaymentPooling;
import com.ys.entity.finance.TcwWanliReconciliation;
import com.ys.entity.finance.TcwWanliReconciliationItem;
import com.ys.entity.flow.YspModel;
import com.ys.entity.sys.TsUserChange;
import com.ys.entity.sys.YsMenu;
import com.ys.entity.sys.YsProcInst;
import com.ys.enume.finance.TcwWanliReconciliationItemEnum;
import com.ys.enume.flow.FlowEnum;
import com.ys.enume.flow.YsProcInstEnum;
import com.ys.mapper.finance.FinanceMapper;
import com.ys.mapper.finance.TcwWanliPrepaymentPoolingMapper;
import com.ys.mapper.finance.TcwWanliReconciliationItemMapper;
import com.ys.mapper.finance.TcwWanliReconciliationMapper;
import com.ys.service.finance.TcwWanliReconciliationService;
import com.ys.service.flow.YspTaskService;
import com.ys.util.shiro.ShiroUtils;
import com.ys.vo.Flow;
import com.ys.vo.R;

@Service("tcwWanliReconciliationService")
public class TcwWanliReconciliationServiceImpl implements TcwWanliReconciliationService {

	@Autowired
	private FinanceMapper financeMapper;
	@Autowired
	private TcwWanliReconciliationMapper tcwWanliReconciliationMapper;
	@Autowired
	private TcwWanliReconciliationItemMapper tcwWanliReconciliationItemMapper;
	@Autowired
	private TcwWanliPrepaymentPoolingMapper tcwWanliPrepaymentPoolingMapper;
	
	
	@Autowired
	private YspTaskService yspTaskService;
	/**
	 * 新增
	 * @param params
	 * @return
	 * @throws Exception
	 */
	@Override
	@Transactional
	public R add(String bid, String depositPlatformCode, String reconciliationDayBegin, String reconciliationDayEnd, String vbz, 
			BigDecimal amountGbp,
			BigDecimal amountUsd,
			BigDecimal amountEur,
			BigDecimal amountCny,
			BigDecimal feeGbp,
			BigDecimal feeUsd,
			BigDecimal feeEur,
			BigDecimal amountGuijiGbp,
			BigDecimal amountGuijiUsd,
			BigDecimal amountGuijiEur, String detailArr, Long menuId) throws Exception {

		if (bid == null || bid.length() == 0) {
			return R.error("单号不能为空");
		} else if(new TcwWanliReconciliation().setBid(bid).count() > 0) {
			return R.error("单号已存在");
		}
		
		if (amountGbp == null || amountUsd == null || amountEur == null) {
			return R.error("使用金额不能为空");
		}
		
		if (amountGuijiGbp == null || amountGuijiUsd == null || amountGuijiEur == null) {
			return R.error("归集金额不能为空");
		}
		
		if (depositPlatformCode == null || depositPlatformCode.length() == 0) {
			return R.error("收款平台账号编码不能为空");
		}
		
		if (reconciliationDayBegin == null || reconciliationDayBegin.length() == 0
				|| reconciliationDayEnd == null || reconciliationDayEnd.length() == 0) {
			return R.error("对账日期不能为空");
		} else if (reconciliationDayBegin.compareTo(reconciliationDayEnd) > 0) {
			return R.error("对账日期格式有误");
		}
		
		/*
		 *  根据付款类型验证详情
		 *  1、归集明细ID不能为空
		 *  2、记录归集金额不能为空
		 */
		JSONArray detailJA = JSON.parseArray(detailArr);
		if (detailJA == null || detailJA.size() == 0) {
			return R.error("详情数据不能为空");
		}
		for (int i = 0; i < detailJA.size(); i++) {
			JSONObject detailJO = detailJA.getJSONObject(i);
			
			Long wanliPrepaymentPoolingId = detailJO.getLong("wanliPrepaymentPoolingId");
			if (wanliPrepaymentPoolingId == null) {
				return R.error("归集明细ID不能为空");
			}
			BigDecimal recordAmountGuiji = detailJO.getBigDecimal("recordAmountGuiji");
			if (recordAmountGuiji == null) {
				return R.error("记录归集金额不能为空");
			}
			
			String vgsbm = detailJO.getString("vgsbm");
			if (vgsbm == null || vgsbm.length() == 0) {
				return R.error("公司编码不能为空");
			}
		}
		
		String loginUserId = ShiroUtils.getUserId();
		TsUserChange tsUserChange = new TsUserChange().setUserId(loginUserId).setStatus(1).queryFirst();
		
		TcwWanliReconciliation entity = null;
		{
			Integer effectStock = FlowEnum.EffectStock.NOT_EFFECT.value;
			Long createChangeId = tsUserChange.getId();
			
			entity = TcwWanliReconciliation.tcwWanliReconciliation(bid, effectStock, createChangeId, depositPlatformCode, reconciliationDayBegin, reconciliationDayEnd, vbz, amountGbp, amountUsd, amountEur, amountCny, feeGbp, feeUsd, feeEur, amountGuijiGbp, amountGuijiUsd, amountGuijiEur, 1);
			tcwWanliReconciliationMapper.insert(entity);
		}
		
		// 添加万里汇预付款对账单明细
		for (int i = 0; i < detailJA.size(); i++) {
			JSONObject detailJO = detailJA.getJSONObject(i);
			
			String pbid = bid;
			Long wanliPrepaymentPoolingId = detailJO.getLong("wanliPrepaymentPoolingId");
			BigDecimal recordAmountGuiji = detailJO.getBigDecimal("recordAmountGuiji");
			TcwWanliReconciliationItem tcwWanliReconciliationItem = TcwWanliReconciliationItem.tcwWanliReconciliationItem(pbid, wanliPrepaymentPoolingId, recordAmountGuiji, 1);
			tcwWanliReconciliationItemMapper.insert(tcwWanliReconciliationItem);
		}
		
		/*
		 * 流程初始化
		 */
		YsMenu ysMenu = new YsMenu().setId(menuId).queryFirst();
		if (ysMenu.getFlowModelId().longValue() != 0L) {
			YspModel yspModel = new YspModel().setId(ysMenu.getFlowModelId()).queryFirst();
			String codeModel = yspModel.getCode();
			String createUserId = ShiroUtils.getUserId();
			yspTaskService.init(codeModel, bid, createUserId);
		}
		return R.ok(AddDto.gotoEdit("/web/finance/tcwWanliReconciliation/toFlow?bid=" + bid));
	}
	
	@Override
	@Transactional
	public R edit(String bid, String depositPlatformCode, String reconciliationDayBegin, String reconciliationDayEnd, String vbz,
			BigDecimal amountGbp,
			BigDecimal amountUsd,
			BigDecimal amountEur,
			BigDecimal amountCny,
			BigDecimal feeGbp,
			BigDecimal feeUsd,
			BigDecimal feeEur,
			BigDecimal amountGuijiGbp,
			BigDecimal amountGuijiUsd,
			BigDecimal amountGuijiEur, String detailArr, Long menuId) throws Exception {

		
		if (reconciliationDayBegin == null || reconciliationDayBegin.length() == 0
				|| reconciliationDayEnd == null || reconciliationDayEnd.length() == 0) {
			return R.error("对账日期不能为空");
		} else if (reconciliationDayBegin.compareTo(reconciliationDayEnd) > 0) {
			return R.error("对账日期格式有误");
		}
		
		if (amountGbp == null || amountUsd == null || amountEur == null) {
			return R.error("使用金额不能为空");
		}
		
		if (amountGuijiGbp == null || amountGuijiUsd == null || amountGuijiEur == null) {
			return R.error("归集金额不能为空");
		}
		
		Integer stateFlow = yspTaskService.flowState(bid);
		if (stateFlow == YsProcInstEnum.StateFlow.FINISH.value) {
			return R.error("已流转结束，无法修改");
		}
		
		/*
		 *  根据付款类型验证详情
		 *  1、归集明细ID不能为空
		 *  2、记录归集金额不能为空
		 */
		JSONArray detailJA = JSON.parseArray(detailArr);
		if (detailJA == null || detailJA.size() == 0) {
			return R.error("详情数据不能为空");
		}
		for (int i = 0; i < detailJA.size(); i++) {
			JSONObject detailJO = detailJA.getJSONObject(i);
			
			Long wanliPrepaymentPoolingId = detailJO.getLong("wanliPrepaymentPoolingId");
			if (wanliPrepaymentPoolingId == null) {
				return R.error("归集明细ID不能为空");
			}
			BigDecimal recordAmountGuiji = detailJO.getBigDecimal("recordAmountGuiji");
			if (recordAmountGuiji == null) {
				return R.error("记录归集金额不能为空");
			}
			
			String vgsbm = detailJO.getString("vgsbm");
			if (vgsbm == null || vgsbm.length() == 0) {
				return R.error("公司编码不能为空");
			}
		}
		
		TcwWanliReconciliation entity = new TcwWanliReconciliation().setBid(bid).queryFirst();
		entity.setDepositPlatformCode(depositPlatformCode)
			.setReconciliationDayBegin(reconciliationDayBegin)
			.setReconciliationDayEnd(reconciliationDayEnd)
			.setVbz(vbz)
			.setAmountEur(amountEur)
			.setAmountGbp(amountGbp)
			.setAmountUsd(amountUsd)
			.setAmountCny(amountCny)
			.setFeeEur(feeEur)
			.setFeeGbp(feeGbp)
			.setFeeUsd(feeUsd)
			.setAmountGuijiEur(amountGuijiEur)
			.setAmountGuijiGbp(amountGuijiGbp)
			.setAmountGuijiUsd(amountGuijiUsd);
		tcwWanliReconciliationMapper.update(entity);
		
		// 删除旧的详情数据
		financeMapper.deleteTcwWanliReconciliationItemByPbid(bid);
		
		// 添加万里汇预付款对账单明细
		for (int i = 0; i < detailJA.size(); i++) {
			JSONObject detailJO = detailJA.getJSONObject(i);
			
			String pbid = bid;
			Long wanliPrepaymentPoolingId = detailJO.getLong("wanliPrepaymentPoolingId");
			BigDecimal recordAmountGuiji = detailJO.getBigDecimal("recordAmountGuiji");
			TcwWanliReconciliationItem tcwWanliReconciliationItem = TcwWanliReconciliationItem.tcwWanliReconciliationItem(
					pbid, wanliPrepaymentPoolingId, recordAmountGuiji, 1);
			tcwWanliReconciliationItemMapper.insert(tcwWanliReconciliationItem);
		}
		
		return R.ok(EditDto.reloadPage("/web/finance/tcwWanliReconciliation/toFlow?bid=" + bid));
	}

	@Override
	@Transactional
	public R deleteTrue(Long id) throws Exception {
		if (id == null) {
			return R.error("ID不能为空");
		}
		
		TcwWanliReconciliation entity = new TcwWanliReconciliation().setId(id).queryFirst();
		if (entity.getEffectStock() == FlowEnum.EffectStock.EFFECTED.value) {
			return R.error("已生效数据无法删除");
		}
		// 验证是否制单人
		String loginUserId = ShiroUtils.getUserId();
		TsUserChange tsUserChange = new TsUserChange().setId(entity.getCreateChangeId()).queryFirst();
		
		if (!tsUserChange.getUserId().equals(loginUserId)) {
			return R.error("非制单人，无法删除");
		}
		
		// 删除主数据
		tcwWanliReconciliationMapper.deleteTrue(id);
		
		// 删除子数据
		List<TcwWanliReconciliationItem> listDetail = new TcwWanliReconciliationItem().setPbid(entity.getBid()).queryList();
		for(TcwWanliReconciliationItem detail : listDetail) {
			tcwWanliReconciliationItemMapper.deleteTrue(detail.getId());
		}
		
		yspTaskService.flowDelete(entity.getBid(), loginUserId);
		return R.ok();
	}

	@Override
	@Transactional
	public R flowPass(String bid, String loginUserId) throws Exception {
		
		// 若流程是初始化状态，需验证数据的可用性
		YsProcInst ysProcInst = new YsProcInst().setBid(bid).queryFirst();
		if (ysProcInst.getStateFlow() == YsProcInstEnum.StateFlow.INIT.value) {
			TcwWanliReconciliation tcwWanliReconciliation = new TcwWanliReconciliation().setBid(bid).queryFirst();
			BigDecimal amountGbp = tcwWanliReconciliation.getAmountGbp();
			BigDecimal amountUsd = tcwWanliReconciliation.getAmountUsd();
			BigDecimal amountEur = tcwWanliReconciliation.getAmountEur();
			BigDecimal amountGuijiGbp = tcwWanliReconciliation.getAmountGuijiGbp();
			BigDecimal amountGuijiUsd = tcwWanliReconciliation.getAmountGuijiUsd();
			BigDecimal amountGuijiEur = tcwWanliReconciliation.getAmountGuijiEur();
			if (amountGbp.compareTo(amountGuijiGbp) != 0 || amountUsd.compareTo(amountGuijiUsd) != 0 || amountEur.compareTo(amountGuijiEur) != 0) {
				return R.error("使用金额与归集金额不一致");
			}
		}

		
		try {
			Flow f = yspTaskService.flowPass(bid, loginUserId);
			if (f.getCode() == Flow.Code.FAILED.value) {
				return R.error(f.getMsg());
			} else {
				
				if (f.getState() == Flow.State.FINISH.value) {
					flowFinish(bid);
				}
				return R.ok();
			}
		} catch (Exception e) {
			e.printStackTrace();
			return R.error("服务器正在开小差，请联系客服");
		}
	}

	@Override
	public R flowRefuse(String bid, String reason, String loginUserId) throws Exception {
		
		R r = yspTaskService.flowRefuse(bid, reason, loginUserId);
		return r;
	}

	@Override
	@Transactional
	public void flowFinish(String bid) throws Exception {

		TcwWanliReconciliation entity = new TcwWanliReconciliation().setBid(bid).queryFirst();
		
		YsProcInst ysProcInst = new YsProcInst().setBid(entity.getBid()).queryFirst();
		if (ysProcInst.getStateFlow() != YsProcInstEnum.StateFlow.FINISH.value) {
			return;
		}
		
		entity.setEffectStock(FlowEnum.EffectStock.EFFECTED.value);
		tcwWanliReconciliationMapper.update(entity);
		
		List<TcwWanliReconciliationItem> listDetail = new TcwWanliReconciliationItem().setPbid(bid).queryList();
		for (TcwWanliReconciliationItem item : listDetail) {
			TcwWanliPrepaymentPooling pooling = new TcwWanliPrepaymentPooling().setId(item.getWanliPrepaymentPoolingId()).queryFirst();
			pooling.setReconciliationStatus(TcwWanliReconciliationItemEnum.ReconciliationStatus.YES.value);
			tcwWanliPrepaymentPoolingMapper.update(pooling);
		}
	}

	//获取列表数据
	@Override
	@Transactional
	public Map<String,Object> getExtraParam(String bid) throws Exception{
		Map<String, Object> extraParam = new TcwWanliReconciliation()
				.setBid(bid)
				.clearFieldsSource()

				.addLeftJoin("YS_ProcInst B99 ON B99.Bid = A.Bid")
				.addField("B99.UpdateTime auditTime")
				.addLeftJoin("TCW_DepositPlatform C on C.Code = A.DepositPlatformCode")
				.addField("C.PlatformName platformName")
				.addField("C.Code depositPlatformCode")
				.addField("C.Name depositPlatformName")

				.addLeftJoin("TB_CompanyInfo D ON D.Vid = C.CompanyVid")
				.addField("D.Vid companyVid")
				.addField("D.Vname companyVname")

				.queryFirstMap();
		return extraParam;
	}
	//获取子列表数据
	@Override
	@Transactional
	public List<Map<String, Object>> getItemList( String bid) throws Exception{
		List<Map<String, Object>> sonlist = new TcwWanliReconciliationItem()
				.setPbid(bid)

				.addLeftJoin("TCW_WanliPrepaymentPooling B ON B.Id = A.WanliPrepaymentPoolingId")
				.addField("B.FkMid fkMid")
				.addField("B.PayerAccountNo payerAccountNo")
				.addField("B.PayerName payerName")
				.addField("B.SkMid skMid")
				.addField("B.BeneficiaryAccountNo beneficiaryAccountNo")
				.addField("B.BeneficiaryName beneficiaryName")
				.addField("B.TransactionType transactionType")
				.addField("B.OriginalTransactionAmount originalTransactionAmount")
				.addField("B.JyCurrencyCode jyCurrencyCode")
				.addField("B.ExtTransactionId extTransactionId")
				.addField("B.TransactionId transactionId")
				.addField("B.TransactionTime transactionTime")
				.addField("B.TransactionStatus transactionStatus")
				.addField("B.Description description")
				.addField("B.fkVyhsx fkVyhsx")
				.addField("B.skVyhsx skVyhsx")

				.addLeftJoin("THR_OperateCompanyApply B3 ON B3.vgsbm = B.vgsbm")//运营公司
				.addField("B3.vgsbm vgsbm")
				.addField("B3.vgsjc vgsjc")

				.queryMap();
		return sonlist;
	}

}
